
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       rc_protocol.h
  * @author     baiyang
  * @date       2022-6-11
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include "rcprotocol_backend.h"

#include <stdint.h>
#include <stdbool.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
typedef struct SerialConfig* SerialConfig_t;

struct SerialConfig {
    uint32_t baud;
    uint8_t parity;
    uint8_t stop_bits;
    bool invert_rx;
};

/** @ 
  * @brief  
  */
struct rc_protocol {
    enum rcprotocol_t _detected_protocol;
    uint16_t _disabled_for_pulses;
    bool _detected_with_bytes;
    rcprotocol_backend_t backend[RCP_NONE];
    bool _new_input;
    uint32_t _last_input_ms;
    bool _failsafe_active;
    bool _valid_serial_prot;

    // optional additional uart
    struct {
        rt_device_t uart;
        bool opened;
        uint32_t last_config_change_ms;
        uint8_t config_num;
    } added;

    // allowed RC protocols mask (first bit means "all")
    uint32_t rc_protocols_mask;
};

/*----------------------------------variable----------------------------------*/
extern struct rc_protocol rcprotocol;
/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void rcprotocol_ctor();
void rcprotocol_init();
bool rcprotocol_should_search(uint32_t now_ms);
void rcprotocol_process_pulse(uint32_t width_s0, uint32_t width_s1);
void rcprotocol_process_pulse_list(const uint32_t *widths, uint16_t n, bool need_swap);
bool rcprotocol_process_byte(uint8_t byte, uint32_t baudrate);
void rcprotocol_process_handshake(uint32_t baudrate);
void rcprotocol_update();
bool rcprotocol_new_input();
uint8_t rcprotocol_num_channels();
uint16_t rcprotocol_read(uint8_t chan);
void rcprotocol_read2(uint16_t *pwm, uint8_t n);
int16_t rcprotocol_get_RSSI(void);
int16_t rcprotocol_get_rx_link_quality(void);
void rcprotocol_start_bind(void);
const char *rcprotocol_protocol_name_from_protocol(enum rcprotocol_t protocol);
const char *rcprotocol_protocol_name(void);

bool rcprotocol_failsafe_active();
void rcprotocol_set_failsafe_active(bool active);
void rcprotocol_disable_for_pulses(enum rcprotocol_t protocol);
bool rcprotocol_using_uart(void);

// for protocols without strong CRCs we require 3 good frames to lock on
static inline bool rcprotocol_requires_3_frames(enum rcprotocol_t p) {
    switch (p) {
    case RCP_DSM:
#if AP_RCPROTOCOL_FASTSBUS_ENABLED
    case RCP_FASTSBUS:
#endif
    case RCP_SBUS:
    case RCP_SBUS_NI:
    case RCP_PPM:
    case RCP_FPORT:
    case RCP_FPORT2:
        return true;
    case RCP_IBUS:
    case RCP_SUMD:
    case RCP_SRXL:
    case RCP_SRXL2:
    case RCP_CRSF:
    case RCP_ST24:
    case RCP_NONE:
        return false;
    }
    return false;
}

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



